from functools import reduce
from operator import and_

from django.db.models import Q
from django.shortcuts import reverse
from django.utils.html import format_html

from rest_framework import viewsets

from oauth2_provider.contrib.rest_framework import TokenHasScope

from prj002.models import info
from prj002.permissions import DiffRolePermisssion
from prj002.serializers import AllSerializer
from prj002.utils.constants import SESSION_DATA


class SCView(viewsets.ModelViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.

    Override .perform_create to custom the save instance
    """
    permission_classes = [TokenHasScope, DiffRolePermisssion]
    required_scopes = ['prj002']

    def get_queryset(self):
        user = self.request.user
        if hasattr(self, 'set_session_data') and getattr(self, 'set_session_data'):
            SESSION_DATA['{}'.format(user.id)] = None

        if user.has_perm('prj002.prj002_all_permissions'):
            return super().get_queryset()

        return self.queryset.filter(owner=user)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class SearchInfoView(SCView):
    """ For search API and fileout API
    : to search info by request data
    """

    def search_instances(self, request_data):
        search_query = []

        for k, v in request_data.items():
            if not v:
                continue

            if hasattr(info.Info, k) or k.startswith('owner'):
                query = '__'.join([k, 'icontains'])
                search_query.append(Q(**{query: v}))

        if search_query:
            srearch_queryset = super().get_queryset().filter(reduce(and_, search_query))
        else:
            srearch_queryset = super().get_queryset()

        return srearch_queryset


class SCAdmin(object):

    def owner_link(self, obj):
        url = reverse('admin:myuser_myuser_change', args=[obj.owner.id])
        return format_html("<a href='{}'>{}</a>", url, obj.owner)

    def info_link(self, obj):
        url = reverse('admin:prj002_info_change', args=[obj.info.id])
        return format_html("<a href='{}'>{}</a>", url, obj.info.serial)

    owner_link.short_description = '账户'
    info_link.short_description = '一般信息ID'


def get_excel_needed(obj):
    inner_data = dict()
    try:
        inner_data['summary'] = obj.summary
    except Exception:
        inner_data['summary'] = None

    try:
        inner_data['standard'] = obj.standard
    except Exception:
        inner_data['standard'] = None

    try:
        inner_data['disease'] = obj.disease
    except Exception:
        inner_data['disease'] = None

    try:
        inner_data['history'] = obj.history
    except Exception:
        inner_data['history'] = None

    try:
        inner_data['experiment'] = obj.experiment
    except Exception:
        inner_data['experiment'] = None

    try:
        inner_data['bxray'] = obj.bxray
    except Exception:
        inner_data['bxray'] = None

    try:
        inner_data['clinical'] = obj.clinical
    except Exception:
        inner_data['clinical'] = None

    try:
        inner_data['cure'] = obj.cure
    except Exception:
        inner_data['cure'] = None
    inner_data['info'] = obj

    all_object_data = AllSerializer(inner_data)
    return all_object_data.data
